package com.atguigu.gmall.filter;

import com.atguigu.gmall.common.util.IpUtil;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;

@Component
public class GmallFilter implements GlobalFilter, Ordered {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //获得request 请求体
        ServerHttpRequest request = exchange.getRequest();
        //获取响应体
        ServerHttpResponse response = exchange.getResponse();
        //从请求参数中获得token
        String token = request.getQueryParams().getFirst("token");
        //判断用户url 中是否携带token
        if (StringUtils.isEmpty(token)){
            //请求参数URL 中没有token 判断 请求头中是否有
            token = request.getHeaders().getFirst("token");
            if (StringUtils.isEmpty(token)){
                //如果请求头中也没有 判断 Cookie 中是否携带
                MultiValueMap<String, HttpCookie> cookies = request.getCookies();
                //cookies 是个map 类型要判断是否为空
                if (cookies != null){
                    HttpCookie cookiesFirst = cookies.getFirst("token");
                    //因为返回值是httpCookie 类型 还是包装类型因此还要判断
                    if (cookiesFirst != null){
                        //获取的是token中的名
                        String name = cookiesFirst.getName();
                        //获取的是cookie的值
                        token = cookiesFirst.getValue();
                    }
                }
            }
        }
        //最后在判断 token是否有值
        if (StringUtils.isEmpty(token)){
            //设置响应状态码
            response.setStatusCode(HttpStatus.NOT_ACCEPTABLE);
            //token为空 没有获得令牌 拒绝请求
           return response.setComplete();
        }
        //校验当前请求IP地址 获取当前用户登录时存入redis中的令牌
        String gatwayIpAddress = IpUtil.getGatwayIpAddress(request);
        //根据IP地址获取用户登录时存入redis中的令牌
        String redisToken = stringRedisTemplate.opsForValue().get(gatwayIpAddress);
        //判断当前用户在拥有令牌
        if (StringUtils.isEmpty(redisToken)){
            response.setStatusCode(HttpStatus.NOT_ACCEPTABLE);
            //当前用户没有令牌 直接拒绝访问
            return response.setComplete();
        }
        //判断当前IP下 用户的令牌与数据库中的是否一致
        if (!redisToken.equals(token)){
            response.setStatusCode(HttpStatus.NOT_ACCEPTABLE);
            //不一致说明IP不匹配
            return response.setComplete();
        }
        //使用mutate属性将token放入 exchange的request中 不使用这个属性不能放进去
        request.mutate().header("Authorization","bearer "+token);
        //过滤器放行
        return chain.filter(exchange);
    }


    @Override
    public int getOrder() {
        return 0;
    }
}
